/**
 * Title :	jFamilyTree generator
 * Description: jFamilyTree generator
 * Version:	provider
 * Copyright (c) 2001-2008
 * Terms of use:see license agreement at http://treebolic.sourceforge.net/en/license.htm
 * Author: Bernard Bou
 * Company: bsys
 */
package jFamilyTree.generator.tree;

import java.util.List;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;

import jFamilyTree.model.IEdge;
import jFamilyTree.model.INode;
import jFamilyTree.model.MenuItem;
import jFamilyTree.model.Model;
import jFamilyTree.model.Node;
import jFamilyTree.model.Settings;

/**
 * Tree adapter (converts jFamilyTree model to DefaultTreeModel)
 * 
 * @author Bernard Bou
 */
public class TreeAdapter extends DefaultTreeModel
{
	private static final long serialVersionUID = 1L;

	/**
	 * Constructor
	 * 
	 * @param thisModel
	 *        jFamilyTree model
	 */
	public TreeAdapter(Model thisModel)
	{
		super(makeTreeModel(thisModel));
	}

	/**
	 * Make tree model out of jFamilyTree model
	 * 
	 * @param thisModel
	 *        jFamilyTree model
	 * @return tree model
	 */
	public static javax.swing.tree.TreeNode makeTreeModel(Model thisModel)
	{
		if (thisModel == null)
			return null;

		// root
		Node thisNode = (Node) thisModel.theTree.getRoot();
		MutableTreeNode thisRootTreeNode = makeNode(thisNode, null);

		// nodes
		DefaultMutableTreeNode thisNodesTreeNode = new DefaultMutableTreeNode();
		thisNodesTreeNode.setUserObject(new NodesWrapper(thisModel.theSettings));
		thisNodesTreeNode.add(thisRootTreeNode);
		thisNodesTreeNode.add(thisRootTreeNode);

		// edges
		List<IEdge> theseEdges = thisModel.theTree.getEdges();
		MutableTreeNode thisEdgesTreeNode = makeEdges(theseEdges, thisModel, thisModel.theSettings);

		// tree
		DefaultMutableTreeNode thisTreeTreeNode = new DefaultMutableTreeNode();
		thisTreeTreeNode.setUserObject(new TreeWrapper(thisModel.theSettings));
		thisTreeTreeNode.add(thisNodesTreeNode);
		thisTreeTreeNode.add(thisEdgesTreeNode);

		// tools
		MutableTreeNode thisToolsTreeNode = makeTools(thisModel.theSettings.theMenu, thisModel.theSettings);

		// top
		DefaultMutableTreeNode thisTreeNode = new DefaultMutableTreeNode();
		thisTreeNode.setUserObject(new TopWrapper(thisModel.theSettings));
		thisTreeNode.add(thisTreeTreeNode);
		thisTreeNode.add(thisToolsTreeNode);
		return thisTreeNode;
	}

	/**
	 * Make tree node for jFamilyTree node
	 * 
	 * @param thisNode
	 *        jFamilyTree node
	 * @param thisParentTreeNode
	 *        parent tree node
	 * @return tree node
	 */
	private static MutableTreeNode makeNode(Node thisNode, MutableTreeNode thisParentTreeNode)
	{
		DefaultMutableTreeNode thisTreeNode = new DefaultMutableTreeNode();
		thisTreeNode.setUserObject(thisNode);

		// recurse
		for (INode thisIChild : thisNode.getChildren())
		{
			Node thisChild = (Node) thisIChild;
			MutableTreeNode thisChildTreeNode = makeNode(thisChild, thisTreeNode);

			// attach child to parent
			thisTreeNode.add(thisChildTreeNode);
		}
		return thisTreeNode;
	}

	/**
	 * Make tree node for edges
	 * 
	 * @param thisEdgeList
	 *        edge list
	 * @param thisModel
	 *        model
	 * @param theseSettings
	 *        settings
	 * @return tree node
	 */
	private static MutableTreeNode makeEdges(List<IEdge> thisEdgeList, Model thisModel, Settings theseSettings)
	{
		// container
		DefaultMutableTreeNode thisEdgesTreeNode = new DefaultMutableTreeNode();
		thisEdgesTreeNode.setUserObject(new EdgesWrapper(thisEdgeList, thisModel, theseSettings));

		// iterate
		if (thisEdgeList != null)
			for (IEdge thisEdge : thisEdgeList)
			{
				DefaultMutableTreeNode thisEdgeTreeNode = new DefaultMutableTreeNode();
				thisEdgeTreeNode.setUserObject(thisEdge);

				// attach to container
				thisEdgesTreeNode.add(thisEdgeTreeNode);
			}
		return thisEdgesTreeNode;
	}

	/**
	 * Make tree node for menu
	 * 
	 * @param thisMenu
	 *        menu
	 * @param theseSettings
	 *        settings
	 * @return tree node
	 */
	private static MutableTreeNode makeTools(List<MenuItem> thisMenu, Settings theseSettings)
	{
		DefaultMutableTreeNode thisToolsTreeNode = new DefaultMutableTreeNode();
		thisToolsTreeNode.setUserObject(new ToolsWrapper(theseSettings));

		DefaultMutableTreeNode thisMenuTreeNode = new DefaultMutableTreeNode();
		thisMenuTreeNode.setUserObject(new MenuWrapper(theseSettings.theMenu, theseSettings));
		thisToolsTreeNode.add(thisMenuTreeNode);

		if (theseSettings.theMenu != null)
		{
			for (MenuItem thisMenuItem : theseSettings.theMenu)
			{
				DefaultMutableTreeNode thisMenuItemTreeNode = new DefaultMutableTreeNode();
				thisMenuItemTreeNode.setUserObject(new MenuItemWrapper(thisMenuItem, theseSettings));
				thisMenuTreeNode.add(thisMenuItemTreeNode);
			}
		}
		return thisToolsTreeNode;
	}
}
